package com.ruoyi.crm.service.impl;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.constant.CrmConstant;
import com.ruoyi.common.core.domain.BaseFlowEntity;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.enums.AuditStatus;
import com.ruoyi.common.enums.erp.CrmOrderProgessEnum;
import com.ruoyi.common.enums.flow.FlowTypeEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.erp.ProjectNoUtils;
import com.ruoyi.common.utils.flow.FlowDTO;
import com.ruoyi.common.utils.flow.FlowParamsUtils;
import com.ruoyi.crm.domain.*;
import com.ruoyi.crm.service.ICrmCustomerService;
import com.ruoyi.crm.service.ICrmOrderRegisterDetailsService;
import com.ruoyi.crm.service.ICrmOrderService;
import com.ruoyi.crm.utils.ThreadLocalUtils;
import com.ruoyi.system.service.ISysDeptService;
import com.warm.flow.core.dto.FlowParams;
import com.warm.flow.core.enums.SkipType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.crm.mapper.CrmOrderRegisterMapper;
import com.ruoyi.crm.service.ICrmOrderRegisterService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.xml.crypto.Data;

/**
 * 商机项目立项Service业务层处理
 *
 * @author yanwenliang
 * @date 2024-11-06
 */
@Service
public class CrmOrderRegisterServiceImpl extends ServiceImpl<CrmOrderRegisterMapper, CrmOrderRegister> implements ICrmOrderRegisterService
{
    @Autowired
    private CrmOrderRegisterMapper crmOrderRegisterMapper;

    @Autowired
    private ISysDeptService sysDeptService;

    @Autowired
    private ICrmOrderRegisterDetailsService crmOrderRegisterDetailsService;

    @Autowired
    private ICrmOrderService crmOrderService;

    @Autowired
    private ICrmCustomerService crmCustomerService;


    /**
     * 查询商机项目立项
     *
     * @param orderRegisterId 商机项目立项主键
     * @return 商机项目立项
     */
    @Override
    public CrmOrderRegister selectCrmOrderRegisterByOrderRegisterId(String orderRegisterId)
    {
        return crmOrderRegisterMapper.selectCrmOrderRegisterByOrderRegisterId(orderRegisterId);
    }

    @Override
    public CrmOrderRegister selectCrmOrderRegisterByOrderId(String orderId) {
        return crmOrderRegisterMapper.selectCrmOrderRegisterByOrderId(orderId);
    }

    /**
     * 查询商机项目立项列表
     *
     * @param crmOrderRegister 商机项目立项
     * @return 商机项目立项
     */
    @Override
    public List<CrmOrderRegister> selectCrmOrderRegisterList(CrmOrderRegister crmOrderRegister)
    {
        return crmOrderRegisterMapper.selectCrmOrderRegisterList(crmOrderRegister);
    }

    /**
     * 新增商机项目立项
     *
     * @param crmOrderRegister 商机项目立项
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertCrmOrderRegister(CrmOrderRegister crmOrderRegister) {
        crmOrderRegister.setCreateTime(DateUtils.getNowDate());
        crmOrderRegister.setCreateBy(SecurityUtils.getUsername());
        crmOrderRegister.setOrderRegisterId(IdWorker.getIdStr());
        crmOrderRegister.setProjectOn(this.generateProjectNo());

        this.computeAmount(crmOrderRegister);
        try {
            ThreadLocalUtils.set(FlowTypeEnum.FLOW_ORDER_REGISTER.getInfo() + ":" + crmOrderRegister.getOrderRegisterId(), crmOrderRegister);

            FlowParamsUtils.start(crmOrderRegister, "flow-order-register", crmOrderRegister.getOrderRegisterId());
            if (AuditStatus.AWAIT_AUDIT.getCode().equals(crmOrderRegister.getAuditStatus())){
                this.submit(crmOrderRegister);
            }

            this.saveDetails(crmOrderRegister);

            return crmOrderRegisterMapper.insertCrmOrderRegister(crmOrderRegister);
        } finally {
            ThreadLocalUtils.remove(FlowTypeEnum.FLOW_ORDER_REGISTER.getInfo() + ":" + crmOrderRegister.getOrderRegisterId());
        }

    }

    /**
     * 生成项目编号
     * @return
     */
    private String generateProjectNo(){
        String date = DateUtils.formatInfo("yyyyMM");

        Long deptId = SecurityUtils.getDeptId();

        String username = SecurityUtils.getUsername();

        String userPrefix = ProjectNoUtils.toFirstLetterUpperCase(username);

        StringBuilder stringBuilder = new StringBuilder();

        SysDept dept = sysDeptService.selectDeptById(deptId);
        String ancestors = dept.getAncestors();

        // 数字事业部则归属江西治桔
        if (CrmConstant.NUMBER_DEPT_ID.equals(deptId.toString()) || ancestors.contains(CrmConstant.NUMBER_DEPT_ID.toString())){
            stringBuilder.append("JXZJ").append(userPrefix).append(date);
        } else {
            stringBuilder.append("JXSN").append(userPrefix).append(date);
        }

        Integer integer = crmOrderRegisterMapper.selectCount(new LambdaQueryWrapper<CrmOrderRegister>()
                .eq(CrmOrderRegister::getCreateBy, SecurityUtils.getUsername())
                .apply("YEAR(create_time) = YEAR({0})", date));

        // 自增并补零（3位数）
        String formattedCount = String.format("%03d", ++integer);
        stringBuilder.append(formattedCount);

        return stringBuilder.toString();
    }



    /**
     * 计算公司项目预计利润，利润率，费用总计
     * @param crmOrderRegister
     */
    private void computeAmount(CrmOrderRegister crmOrderRegister){
        List<CrmOrderRegisterDetails> detailsList = crmOrderRegister.getDetailsList();

        // 计算费用总计
        BigDecimal aggregationCharge = BigDecimal.ZERO;
        for (CrmOrderRegisterDetails crmOrderRegisterDetails : detailsList) {
            // 选择了无，则直接跳过
            if ("1".equals(crmOrderRegisterDetails.getIsRequired())) continue;

            aggregationCharge = aggregationCharge.add(ObjectUtils.isEmpty(crmOrderRegisterDetails.getDetailsAmount()) ? BigDecimal.ZERO : crmOrderRegisterDetails.getDetailsAmount());
        }
        crmOrderRegister.setAggregationCharge(aggregationCharge);

        // 计算利润
        BigDecimal projectSum = crmOrderRegister.getProjectSum();
        BigDecimal profit = projectSum.subtract(aggregationCharge);
        crmOrderRegister.setProfit(profit);

        // 计算利润率
        BigDecimal profitMargin = profit.divide(projectSum, 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100"));
        crmOrderRegister.setProfitMargin(profitMargin);
    }

    /**
     * 新增项目详情
     * @param crmOrderRegister
     */
    private void saveDetails(CrmOrderRegister crmOrderRegister){
        List<CrmOrderRegisterDetails> detailsList = crmOrderRegister.getDetailsList();
        detailsList.forEach(item -> {
            item.setDetailsId(IdWorker.getIdStr());
            item.setOrderRegisterId(crmOrderRegister.getOrderRegisterId());
            item.setUserId(SecurityUtils.getUserId());
            item.setCreateTime(new Date());
        });

        crmOrderRegisterDetailsService.saveBatch(detailsList);
    }

    /**
     * 修改商机项目立项
     *
     * @param crmOrderRegister 商机项目立项
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateCrmOrderRegister(CrmOrderRegister crmOrderRegister) {
        crmOrderRegister.setUpdateTime(DateUtils.getNowDate());
        crmOrderRegister.setUpdateBy(SecurityUtils.getUsername());

        CrmOrderRegister orderRegister = baseMapper.selectById(crmOrderRegister.getOrderRegisterId());

        if (ObjectUtils.isEmpty(orderRegister)){
            throw new ServiceException("项目立项不存在，请刷新后重试");
        }

        this.computeAmount(crmOrderRegister);

        // 删除原来的项目明细
        crmOrderRegisterDetailsService.remove(new LambdaQueryWrapper<CrmOrderRegisterDetails>()
                .eq(CrmOrderRegisterDetails::getOrderRegisterId, crmOrderRegister.getOrderRegisterId()));

        this.saveDetails(crmOrderRegister);
        try {
            ThreadLocalUtils.set(FlowTypeEnum.FLOW_ORDER_REGISTER.getInfo() + ":" + crmOrderRegister.getOrderRegisterId(), crmOrderRegister);
            // 如果项目处于待提交状态，则直接修改
            if (AuditStatus.AWAIT_SUBMIT.getCode().equals(orderRegister.getAuditStatus())){

                // 如果新立项状态为提交，则执行流程
                if (AuditStatus.AWAIT_AUDIT.getCode().equals(crmOrderRegister.getAuditStatus())) {
                    this.submit(crmOrderRegister);
                }

                return crmOrderRegisterMapper.updateCrmOrderRegister(crmOrderRegister);
            }


            // 如果当前项目处于待审核也直接修改
            if (AuditStatus.AWAIT_AUDIT.getCode().equals(orderRegister.getAuditStatus())){

                // 如果新结算状态为暂存，则删除流程
                if (AuditStatus.AWAIT_SUBMIT.getCode().equals(crmOrderRegister.getAuditStatus())) {
                    FlowParamsUtils.remove(orderRegister.getInstanceId());
                    // 开启新流程
                    FlowParamsUtils.start(crmOrderRegister, "flow-order-register", crmOrderRegister.getOrderRegisterId());
                }

                return crmOrderRegisterMapper.updateCrmOrderRegister(crmOrderRegister);
            }

            // 在审核中，则删除原来流程
            if (AuditStatus.IN_AUDIT.getCode().equals(orderRegister.getAuditStatus())){
                FlowParamsUtils.remove(orderRegister.getInstanceId());
            }

            // 开启新流程
            FlowParamsUtils.start(crmOrderRegister, "flow-order-register", crmOrderRegister.getOrderRegisterId());

            // 如果新立项状态为提交，则执行流程
            if (AuditStatus.AWAIT_AUDIT.getCode().equals(crmOrderRegister.getAuditStatus())) {
                this.submit(crmOrderRegister);
            }

            return crmOrderRegisterMapper.updateCrmOrderRegister(crmOrderRegister);
        } finally {
            ThreadLocalUtils.remove(FlowTypeEnum.FLOW_ORDER_REGISTER.getInfo() + ":" + crmOrderRegister.getOrderRegisterId());
        }
    }

    /**
     * 批量删除商机项目立项
     *
     * @param orderRegisterIds 需要删除的商机项目立项主键
     * @return 结果
     */
    @Override
    public int deleteCrmOrderRegisterByOrderRegisterIds(String[] orderRegisterIds) {
        List<CrmOrderRegister> crmOrderRegisters = baseMapper.selectBatchIds(Arrays.asList(orderRegisterIds));
        List<Long> instanceIdList = crmOrderRegisters.stream().map(CrmOrderRegister::getInstanceId).collect(Collectors.toList());
        FlowParamsUtils.remove(instanceIdList);
        return crmOrderRegisterMapper.deleteCrmOrderRegisterByOrderRegisterIds(orderRegisterIds);
    }

    /**
     * 删除商机项目立项信息
     *
     * @param orderRegisterId 商机项目立项主键
     * @return 结果
     */
    @Override
    public int deleteCrmOrderRegisterByOrderRegisterId(String orderRegisterId) {
        return crmOrderRegisterMapper.deleteCrmOrderRegisterByOrderRegisterId(orderRegisterId);
    }

    /**
     * 审核
     * @param crmOrderRegister
     * @return
     */
    @Override
    public int audit(CrmOrderRegister crmOrderRegister) {
        CrmOrderRegister orderRegister = baseMapper.selectById(crmOrderRegister.getOrderRegisterId());

        if (ObjectUtils.isEmpty(orderRegister)){
            throw new ServiceException("项目立项数据不存在，请刷新后重试");
        }

        CrmOrder order = crmOrderService.getById(crmOrderRegister.getOrderId());

        if (ObjectUtils.isEmpty(order)){
            throw new ServiceException("商机数据不存在，请刷新后重试");
        }

        FlowParamsUtils.skip(crmOrderRegister, "");

        if (AuditStatus.PASS.getCode().equals(crmOrderRegister.getAuditStatus())){
            // 修改商机进度，立项成功则进度为90%
            order.setOrderId(crmOrderRegister.getOrderId());
            order.setProgess(CrmOrderProgessEnum.BIDDING.getCode());
            crmOrderService.updateCrmOrderInfo(order);
        }

        return baseMapper.updateById(crmOrderRegister);
    }

    /**
     * 获取项目立项数据
     * @param crmOrderRegister
     * @return
     */
    @Override
    public CrmOrderRegister getOrderRegisterInfo(CrmOrderRegister crmOrderRegister) {
        CrmOrder order = crmOrderService.getById(crmOrderRegister.getOrderId());
        crmOrderRegister.setApplyUser(order.getUserId());
        return baseMapper.getOrderRegisterInfo(crmOrderRegister);
    }

    /**
     * 提交
     * @param crmOrderRegister
     * @return
     */
    private void submit(CrmOrderRegister crmOrderRegister) {
        crmOrderRegister.setSkipType(SkipType.PASS.getKey());
        FlowParams flowParams = FlowParamsUtils.build(crmOrderRegister, "");
        FlowParamsUtils.skipByInsId(crmOrderRegister, flowParams);
    }

    @Override
    public FlowDTO conversionObj(Serializable id) {
        CrmOrderRegister crmOrderRegister = baseMapper.getById(id.toString());
        FlowDTO flowDTO = this.buildFlowDTO(crmOrderRegister);
        return flowDTO;
    }

    @Override
    public FlowDTO conversionObjByLocal(Serializable id) {
        CrmOrderRegister crmOrderRegister = ThreadLocalUtils.get(FlowTypeEnum.FLOW_ORDER_REGISTER.getInfo() + ":" + id);
        CrmCustomer customer = crmCustomerService.getById(crmOrderRegister.getCustomerId());
        crmOrderRegister.setCustomerName(customer.getCustomerName());
        FlowDTO flowDTO = this.buildFlowDTO(crmOrderRegister);
        return flowDTO;
    }


    private FlowDTO buildFlowDTO(CrmOrderRegister crmOrderRegister){
        FlowDTO flowDTO = new FlowDTO(crmOrderRegister);
        Map<String, Object> businessValue = flowDTO.getBusinessValue();
        businessValue.put("项目名称", crmOrderRegister.getProjectName());
        businessValue.put("项目编号", crmOrderRegister.getProjectOn());
        businessValue.put("客户名称", crmOrderRegister.getCustomerName());
        businessValue.put("立项时间", DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", crmOrderRegister.getProjectTime()));
        return flowDTO;
    }
}
